package net.lb.io.json.field;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import net.lb.baseutil.collection.ObjectCollect;
import net.lb.baseutil.collection.StringCache;
import net.lb.io.json.JsonArray;
import net.lb.io.json.JsonObject;
import net.lb.io.json.util.CycleException;
import net.lb.io.json.util.JsonConfig;
import net.lb.io.json.util.JsonSerializer;

@SuppressWarnings("restriction")
public class ObjectField extends JsonField
{
    private Type type;
    
    public ObjectField(Field field)
    {
        super(field);
        type = field.getGenericType();
    }
    
    @Override
    public void setOneDimension(Object value, JsonArray jsonArray, ObjectCollect collect)
    {
        Object[] array = (Object[]) value;
        collect.ensureCapacity(array.length);
        for (Object each : array)
        {
            if (collect.addWithoutEnsureCapacity(each) == false)
            {
                throw new CycleException(each);
            }
            jsonArray.add(JsonConfig.getSerializer(each.getClass()).transToJsonvalue(each, collect));
        }
    }
    
    @Override
    protected Object getSinlgeJsonValue(Object host, ObjectCollect collect)
    {
        Object value = unsafe.getObject(host, offset);
        return JsonConfig.getSerializer(value.getClass()).transToJsonvalue(value, collect);
    }
    
    @Override
    protected void writeToStringByOneDimension(StringCache cache, Object value, ObjectCollect collect)
    {
        cache.append('[', 10);
        for (Object each : (Object[]) value)
        {
            if (each != null)
            {
                JsonConfig.getSerializer(each.getClass()).writeToString(cache, each, collect);
                cache.append(',');
            }
        }
        if (cache.isCommaLast())
        {
            cache.deleteLast();
        }
        cache.append(']');
    }
    
    @Override
    protected void singleWriteToStr(StringCache cache, Object host, ObjectCollect collect)
    {
        Object value = unsafe.getObject(host, offset);
        if (value != null)
        {
            cache.append(jsonKey);
            JsonConfig.getSerializer(value.getClass()).writeToString(cache, value, collect);
            cache.append(',');
        }
    }
    
    @Override
    protected void fillSingle(JsonObject jsonObject, Object target)
    {
        Object value = jsonObject.get(name);
        if (value != null)
        {
            if ((type).equals(Object.class))
            {
                unsafe.putObject(target, offset, JsonConfig.getSerializer(Object.class).toBean(value, type));
            }
            else
            {
                if (type instanceof Class<?>)
                {
                    unsafe.putObject(target, offset, JsonConfig.getSerializer((Class<?>) type).toBean(value, type));
                }
                else
                {
                    unsafe.putObject(target, offset, JsonConfig.getSerializer(value.getClass()).toBean(value, type));
                }
            }
        }
    }
    
    @Override
    protected Object getOneDimensionArray(JsonArray jsonArray)
    {
        JsonSerializer serializer = JsonConfig.getSerializer(rootType);
        int length = jsonArray.size();
        Object array = Array.newInstance(rootType, length);
        for (int i = 0; i < length; i++)
        {
            Array.set(array, i, serializer.toBean(jsonArray.get(i), rootType));
        }
        return array;
    }
    
}
